////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_CONCURRENCY_SPIN_LOCK_INL__
#define __WN_CONCURRENCY_SPIN_LOCK_INL__

#include "WNCore/inc/WNPlatform.h"
#include "WNCore/inc/WNTypes.h"
#include "WNCore/inc/WNAssert.h"
#include "WNCore/inc/WNMacros.h"
#include "WNCore/inc/WNAtomic.h"
#include "WNConcurrency/inc/WNThread.h"

namespace WNConcurrency {
    WN_INLINE WNSpinLock::WNSpinLock() :
        mCounter(0) {
    }

    WN_INLINE WN_VOID WNSpinLock::Lock() {
        while (WNAtomicCompareSwap(&mCounter, 1, 0) != 0) {
            WNThreadYield();
        }
    }

    WN_INLINE WN_BOOL WNSpinLock::TryLock() {
        return(WNAtomicCompareSwap(&mCounter, 1, 0) == 0 ? WN_TRUE : WN_FALSE);
    }

    WN_INLINE WN_VOID WNSpinLock::Unlock() {
        WNAtomicSwap(&mCounter, 0);
    }

    WN_INLINE WNSpinLockScopeLock::WNSpinLockScopeLock(WNSpinLock& _spinLock) :
        mLocked(WN_TRUE),
        mSpinLock(_spinLock) {
        mSpinLock.Lock();
    }

    WN_INLINE WNSpinLockScopeLock::~WNSpinLockScopeLock() {
        if (mLocked) {
            mSpinLock.Unlock();

            mLocked = WN_FALSE;
        }
    }
}

#endif // __WN_CONCURRENCY_SPIN_LOCK_INL__